import basebackend
import pymongo

class MongoBackend(basebackend.BaseBackend):

    def __init__(self, config):
        basebackend.BaseBackend.__init__(self, config, "_id")

    def _getDict(self, document):
        resultdict = {}
        for field in document.getFields():
            resultdict[field] = getattr(document, field)
        for (docname, attrname), field in document.getForeignFields().items():
            resultdict[docname + "_" + attrname] = field.get_value()
        return resultdict

    def _buildDict(self, document):
        resultdict = self._getDict(document)
        #for reference in document.getReferences():
        #    resultdict[reference] = self._buildDict(
        #        getattr(document, reference))
        # ha lazy a referencia, es meg nem toltodott be, nem kell vele foglalkozni
        if not document.isNew():
            resultdict[self._keyName] = document.getKey()
        return resultdict

    def _getCollection(self, documentcls):
        return getattr(self.db, documentcls.getName())

    def connect(self):
        self.conn = pymongo.Connection(self._config.db_settings['host'],
                                       self._config.db_settings['port'])
        self.db = getattr(self.conn, self._config.db_settings['db'])

    def disconnect(self):
        self.conn.disconnect()

    def getByKey(self, documentcls, key):
        collection = self._getCollection(documentcls)

        resultdict = collection.find_one({self._keyName: pymongo.objectid.ObjectId(key)})
        key = resultdict.pop(self._keyName)
        resultobj = documentcls(**resultdict)
        resultobj.setKey(key)
        resultobj.setDirty(False)
        resultobj.setNew(False)

        return resultobj

    def get(self, documentcls, criterias):
        # < > like and or distinct
        #attribute_list, criterias, limit, order
        # cassandraval nem megvalosithato az or, programozottan kell
        # cassandraval nincs like, csak szoeleji egyezes a keyre
        spec = {}
        for crit in criterias:
            if crit.operator == "=":
                spec[crit.field] = crit.value
            elif crit.operator == "<":
                spec[crit.field] = {"$lt": crit.value}
            elif crit.operator == ">":
                spec[crit.field] = {"$gt": crit.value}
            elif crit.operator == "<=":
                spec[crit.field] = {"$lte": crit.value}
            elif crit.operator == ">=":
                spec[crit.field] = {"$gte": crit.value}
            else:
                #TODO: hibakezeles
                pass
        collection = self._getCollection(documentcls)
        
        resultdicts = collection.find(spec)
        resultobjs = []
        for resultdict in resultdicts:
            key = resultdict.pop(self._keyName)
            resultobj = documentcls(**resultdict)
            resultobj.setKey(key)
            resultobj.setDirty(False)
            resultobj.setNew(False)
            resultobjs.append(resultobj)
            
        return resultobjs

    def _save(self, document):
        savedict = self._buildDict(document)
        collection = self._getCollection(document)
        return collection.save(savedict, safe=True)

    def insert(self, document):
        return self._save(document)

    def update(self, document):
        return self._save(document)

    def delete(self, document):
        if document.isNew():
            return
        collection = self._getCollection(document)
        collection.remove(document.getKey())
